<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>math.js | web workers</title>
</head>
<body>

<p>
  In this example, a math.js parser is running in a separate
  <a href="https://www.html5rocks.com/en/tutorials/workers/basics/">web worker</a>,
  preventing the user interface from freezing during heavy calculations.
</p>

<p id="results"></p>

<script>
  /**
   * MathWorker evaluates expressions asynchronously in a web worker.
   *
   * Example usage:
   *
   *     const worker = new MathWorker()
   *     const expr = '12 / (2.3 + 0.7)'
   *     worker.evaluate(expr, function (err, result) {
   *       console.log(err, result)
   *     })
   */
  function MathWorker () {
    this.worker = new Worker('worker.js')
    this.callbacks = {}
    this.seq = 0

    // create a listener to receive responses from the web worker
    const me = this
    this.worker.addEventListener('message', function(event) {
      const response = JSON.parse(event.data)

      // find the callback corresponding to this response
      const callback = me.callbacks[response.id]
      delete me.callbacks[response.id]

      // call the requests callback with the result
      callback(response.err, response.result)
    }, false)
  }

  /**
   * Evaluate an expression
   * @param {string} expr
   * @param {Function} callback   Called as callback(err, result)
   */
  MathWorker.prototype.evaluate = function evaluate (expr, callback) {
    // build a request,
    // add an id so we can link returned responses to the right callback
    const id = this.seq++
    const request = {
      id: id,
      expr: expr
    }

    // queue the callback, it will be called when the worker returns the result
    this.callbacks[id] = callback

    // send the request to the worker
    this.worker.postMessage(JSON.stringify(request))
  }

  // create a MathWorker
  const worker = new MathWorker()

  // evaluate an expression via the worker
  worker.evaluate('12 / (2.3 + 0.7)', function (err, result) {
    document.getElementById('results').innerHTML += 'result: ' + result + '<br>'
  })

</script>

</body>
</html>